home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / gas_251.zip / bin_251 / gprof / printgprof.c < prev    next >
C/C++ Source or Header  |  1994-10-21  |  21KB  |  788 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that: (1) source distributions retain this entire copyright
  7.  * notice and comment, and (2) distributions including binaries display
  8.  * the following acknowledgement:  ``This product includes software
  9.  * developed by the University of California, Berkeley and its contributors''
  10.  * in the documentation or other materials provided with the distribution
  11.  * and in all advertising materials mentioning features or use of this
  12.  * software. Neither the name of the University nor the names of its
  13.  * contributors may be used to endorse or promote products derived
  14.  * from this software without specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #ifndef lint
  21. static char sccsid[] = "@(#)printgprof.c    5.7 (Berkeley) 6/1/90";
  22. #endif /* not lint */
  23.  
  24. #include "gprof.h"
  25. #include <demangle.h>
  26.  
  27. printprof()
  28. {
  29.     register nltype    *np;
  30.     nltype        **sortednlp;
  31.     int            index, timecmp();
  32.  
  33.     actime = 0.0;
  34.     if ( bsd_style_output ) {
  35.     printf( "\f\n" );
  36.     if ( bflag) {
  37.         printf( "\n\n\nflat profile:\n" );
  38.         flat_blurb(stdout);
  39.     }
  40.     }
  41.     else
  42.     printf ("Flat profile:\n");
  43.     flatprofheader();
  44.     /*
  45.      *    Sort the symbol table in by time
  46.      */
  47.     sortednlp = (nltype **) calloc( nname , sizeof(nltype *) );
  48.     if ( sortednlp == (nltype **) 0 ) {
  49.     fprintf( stderr , "[printprof] ran out of memory for time sorting\n" );
  50.     }
  51.     for ( index = 0 ; index < nname ; index += 1 ) {
  52.     sortednlp[ index ] = &nl[ index ];
  53.     }
  54.     qsort( sortednlp , nname , sizeof(nltype *) , timecmp );
  55.     for ( index = 0 ; index < nname ; index += 1 ) {
  56.     np = sortednlp[ index ];
  57.     flatprofline( np );
  58.     }
  59.     actime = 0.0;
  60.     free( sortednlp );
  61.     if ( bflag && !bsd_style_output ) {
  62.     flat_blurb(stdout);
  63.     }
  64. }
  65.  
  66. timecmp( npp1 , npp2 )
  67.     nltype **npp1, **npp2;
  68. {
  69.     double    timediff;
  70.     long    calldiff;
  71.  
  72.     timediff = (*npp2) -> time - (*npp1) -> time;
  73.     if ( timediff > 0.0 )
  74.     return 1 ;
  75.     if ( timediff < 0.0 )
  76.     return -1;
  77.     calldiff = (*npp2) -> ncall - (*npp1) -> ncall;
  78.     if ( calldiff > 0 )
  79.     return 1;
  80.     if ( calldiff < 0 )
  81.     return -1;
  82.     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
  83. }
  84.  
  85.     /*
  86.      *    header for flatprofline
  87.      */
  88. flatprofheader()
  89. {
  90.     
  91.     if (bsd_style_output) {
  92.     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
  93.            (long) scale * sizeof(UNIT) );
  94.     if (totime > 0.0)
  95.       printf(" for %.2f%% of %.2f seconds\n\n", 100.0/totime, totime / hz);
  96.     }
  97.     else {
  98.     printf( "\nEach sample counts as %g seconds.\n",
  99.            1.0 / hz);
  100.     }
  101.     if (totime <= 0.0)
  102.       {
  103.     printf(" no time accumulated\n\n");
  104.     /* This doesn't hurt since all the numerators will be zero.  */
  105.     totime = 1.0;
  106.       }
  107.     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
  108.         "%  " , "cumulative" , "self  " , "" , "self  " , "total " , "" );
  109.     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
  110.         "time" , "seconds " , "seconds" , "calls" ,
  111.         "ms/call" , "ms/call" , "name" );
  112. }
  113.  
  114. flatprofline( np )
  115.     register nltype    *np;
  116. {
  117.  
  118.     if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) {
  119.     return;
  120.     }
  121.     actime += np -> time;
  122.     if (bsd_style_output)
  123.     printf( "%5.1f %10.2f %8.2f" ,
  124.            100 * np -> time / totime , actime / hz , np -> time / hz );
  125.     else
  126.     printf( "%6.2f %9.2f %8.2f" ,
  127.            100 * np -> time / totime , actime / hz , np -> time / hz );
  128.     if ( np -> ncall != 0 ) {
  129.     printf( " %8d %8.2f %8.2f  " , np -> ncall ,
  130.         1000 * np -> time / hz / np -> ncall ,
  131.         1000 * ( np -> time + np -> childtime ) / hz / np -> ncall );
  132.     } else {
  133.     printf( " %8.8s %8.8s %8.8s  " , "" , "" , "" );
  134.     }
  135.     if (bsd_style_output)
  136.     printname( np );
  137.     else
  138.     printnameonly( np );
  139.     printf( "\n" );
  140. }
  141.  
  142. gprofheader()
  143. {
  144.  
  145.     if (!bsd_style_output)
  146.     if (bflag)
  147.         printf ("\t\t     Call graph (explanation follows)\n\n");
  148.     else
  149.         printf ("\t\t\tCall graph\n\n");
  150.     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
  151.         (long) scale * sizeof(UNIT) );
  152.     if ( printtime > 0.0 ) {
  153.     printf( " for %.2f%% of %.2f seconds\n\n" ,
  154.         100.0/printtime , printtime / hz );
  155.     } else {
  156.     printf( " no time propagated\n\n" );
  157.         /*
  158.          *    this doesn't hurt, since all the numerators will be 0.0
  159.          */
  160.     printtime = 1.0;
  161.     }
  162.     if (bsd_style_output) {
  163.     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
  164.            "" , "" , "" , "" , "called" , "total" , "parents");
  165.     printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
  166.            "index" , "%time" , "self" , "descendents" ,
  167.            "called" , "self" , "name" , "index" );
  168.     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
  169.            "" , "" , "" , "" , "called" , "total" , "children");
  170.     printf( "\n" );
  171.     } else {
  172.     printf( "index %% time    self  children    called     name\n" );
  173.     }
  174. }
  175.  
  176. gprofline( np )
  177.     register nltype    *np;
  178. {
  179.     char    kirkbuffer[ BUFSIZ ];
  180.  
  181.     sprintf( kirkbuffer , "[%d]" , np -> index );
  182.     printf(bsd_style_output
  183.        ? "%-6.6s %5.1f %7.2f %11.2f"
  184.        : "%-6.6s %5.1f %7.2f %7.2f" ,
  185.        kirkbuffer ,
  186.        100 * ( np -> propself + np -> propchild ) / printtime ,
  187.        np -> propself / hz ,
  188.        np -> propchild / hz );
  189.     if ( ( np -> ncall + np -> selfcalls ) != 0 ) {
  190.     printf( " %7d" , np -> ncall );
  191.     if ( np -> selfcalls != 0 ) {
  192.         printf( "+%-7d " , np -> selfcalls );
  193.     } else {
  194.         printf( " %7.7s " , "" );
  195.     }
  196.     } else {
  197.     printf( " %7.7s %7.7s " , "" , "" );
  198.     }
  199.     printname( np );
  200.     printf( "\n" );
  201. }
  202.  
  203. printgprof(timesortnlp)
  204.     nltype    **timesortnlp;
  205. {
  206.     int        index;
  207.     nltype    *parentp;
  208.  
  209.     /*
  210.      *    Print out the structured profiling list
  211.      */
  212.     if ( bflag && bsd_style_output ) {
  213.     bsd_callg_blurb(stdout);
  214.     }
  215.     gprofheader();
  216.     for ( index = 0 ; index < nname + ncycle ; index ++ ) {
  217.     parentp = timesortnlp[ index ];
  218.     if ( zflag == 0 &&
  219.          parentp -> ncall == 0 &&
  220.          parentp -> selfcalls == 0 &&
  221.          parentp -> propself == 0 &&
  222.          parentp -> propchild == 0 ) {
  223.         continue;
  224.     }
  225.     if ( ! parentp -> printflag ) {
  226.         continue;
  227.     }
  228.     if ( parentp -> name == 0 && parentp -> cycleno != 0 ) {
  229.         /*
  230.          *    cycle header
  231.          */
  232.         printcycle( parentp );
  233.         printmembers( parentp );
  234.     } else {
  235.         printparents( parentp );
  236.         gprofline( parentp );
  237.         printchildren( parentp );
  238.     }
  239.     if (bsd_style_output)
  240.         printf( "\n" );
  241.     printf( "-----------------------------------------------\n" );
  242.     if (bsd_style_output)
  243.         printf( "\n" );
  244.     }
  245.     free( timesortnlp );
  246.     if ( bflag && !bsd_style_output) {
  247.     fsf_callg_blurb(stdout);
  248.     }
  249. }
  250.  
  251.     /*
  252.      *    sort by decreasing propagated time
  253.      *    if times are equal, but one is a cycle header,
  254.      *        say that's first (e.g. less, i.e. -1).
  255.      *    if one's name doesn't have an underscore and the other does,
  256.      *        say the one is first.
  257.      *    all else being equal, sort by names.
  258.      */
  259. int
  260. totalcmp( npp1 , npp2 )
  261.     nltype    **npp1;
  262.     nltype    **npp2;
  263. {
  264.     register nltype    *np1 = *npp1;
  265.     register nltype    *np2 = *npp2;
  266.     double        diff;
  267.  
  268.     diff =    ( np1 -> propself + np1 -> propchild )
  269.         - ( np2 -> propself + np2 -> propchild );
  270.     if ( diff < 0.0 )
  271.         return 1;
  272.     if ( diff > 0.0 )
  273.         return -1;
  274.     if ( np1 -> name == 0 && np1 -> cycleno != 0 ) 
  275.     return -1;
  276.     if ( np2 -> name == 0 && np2 -> cycleno != 0 )
  277.     return 1;
  278.     if ( np1 -> name == 0 )
  279.     return -1;
  280.     if ( np2 -> name == 0 )
  281.     return 1;
  282.     if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
  283.     return -1;
  284.     if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
  285.     return 1;
  286.     if ( np1 -> ncall > np2 -> ncall )
  287.     return -1;
  288.     if ( np1 -> ncall < np2 -> ncall ) 
  289.     return 1;
  290.     return strcmp( np1 -> name , np2 -> name );
  291. }
  292.  
  293. printparents( childp )
  294.     nltype    *childp;
  295. {
  296.     nltype    *parentp;
  297.     arctype    *arcp;
  298.     nltype    *cycleheadp;
  299.  
  300.     if ( childp -> cyclehead != 0 ) {
  301.     cycleheadp = childp -> cyclehead;
  302.     } else {
  303.     cycleheadp = childp;
  304.     }
  305.     if ( childp -> parents == 0 ) {
  306.     printf(bsd_style_output 
  307.            ? "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s     <spontaneous>\n"
  308.            : "%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s     <spontaneous>\n" ,
  309.         "" , "" , "" , "" , "" , "" );
  310.     return;
  311.     }
  312.     sortparents( childp );
  313.     for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) {
  314.     parentp = arcp -> arc_parentp;
  315.     if ( childp == parentp ||
  316.          ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) {
  317.         /*
  318.          *    selfcall or call among siblings
  319.          */
  320.         printf(bsd_style_output
  321.            ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     "
  322.            : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s     " ,
  323.             "" , "" , "" , "" ,
  324.             arcp -> arc_count , "" );
  325.         printname( parentp );
  326.         printf( "\n" );
  327.     } else {
  328.         /*
  329.          *    regular parent of child
  330.          */
  331.         printf(bsd_style_output
  332.            ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     "
  333.            : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d     ",
  334.             "" , "" ,
  335.             arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
  336.             arcp -> arc_count , cycleheadp -> ncall );
  337.         printname( parentp );
  338.         printf( "\n" );
  339.     }
  340.     }
  341. }
  342.  
  343. printchildren( parentp )
  344.     nltype    *parentp;
  345. {
  346.     nltype    *childp;
  347.     arctype    *arcp;
  348.  
  349.     sortchildren( parentp );
  350.     arcp = parentp -> children;
  351.     for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
  352.     childp = arcp -> arc_childp;
  353.     if ( childp == parentp ||
  354.         ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) {
  355.         /*
  356.          *    self call or call to sibling
  357.          */
  358.         printf(bsd_style_output
  359.            ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     "
  360.            : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s     " ,
  361.            "" , "" , "" , "" , arcp -> arc_count , "" );
  362.         printname( childp );
  363.         printf( "\n" );
  364.     } else {
  365.         /*
  366.          *    regular child of parent
  367.          */
  368.         printf(bsd_style_output
  369.            ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     "
  370.            : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d     " ,
  371.            "" , "" ,
  372.            arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
  373.            arcp -> arc_count , childp -> cyclehead -> ncall );
  374.         printname( childp );
  375.         printf( "\n" );
  376.     }
  377.     }
  378. }
  379.  
  380. /* Print name of symbol.  Return number of characters printed. */
  381.  
  382. int
  383. printnameonly ( selfp )
  384.     nltype    *selfp;
  385. {
  386.     int size = 0;
  387.     CONST char *name = selfp->name;
  388.     if (name != NULL) {
  389.     char *demangled = NULL;
  390.     if (!bsd_style_output) {
  391.         if (name[0] == '_' && name[1] && discard_underscores)
  392.         name++;
  393.         demangled = cplus_demangle (name, DMGL_ANSI|DMGL_PARAMS);
  394.         if (demangled)
  395.         name = demangled;
  396.     }
  397.     printf( "%s" , name );
  398.     size = strlen (name);
  399.     if (demangled)
  400.         free (demangled);
  401. #ifdef DEBUG
  402.     if ( debug & DFNDEBUG ) {
  403.         printf( "{%d} " , selfp -> toporder );
  404.     }
  405.     if ( debug & PROPDEBUG ) {
  406.         printf( "%5.2f%% " , selfp -> propfraction );
  407.     }
  408. #endif DEBUG
  409.     }
  410.     return size;
  411. }
  412.  
  413. printname( selfp )
  414.     nltype    *selfp;
  415. {
  416.     printnameonly (selfp);
  417.  
  418.     if ( selfp -> cycleno != 0 ) {
  419.     printf( " <cycle %d>" , selfp -> cycleno );
  420.     }
  421.     if ( selfp -> index != 0 ) {
  422.     if ( selfp -> printflag ) {
  423.         printf( " [%d]" , selfp -> index );
  424.     } else {
  425.         printf( " (%d)" , selfp -> index );
  426.     }
  427.     }
  428. }
  429.  
  430. sortchildren( parentp )
  431.     nltype    *parentp;
  432. {
  433.     arctype    *arcp;
  434.     arctype    *detachedp;
  435.     arctype    sorted;
  436.     arctype    *prevp;
  437.  
  438.     /*
  439.      *    unlink children from parent,
  440.      *    then insertion sort back on to sorted's children.
  441.      *        *arcp    the arc you have detached and are inserting.
  442.      *        *detachedp    the rest of the arcs to be sorted.
  443.      *        sorted    arc list onto which you insertion sort.
  444.      *        *prevp    arc before the arc you are comparing.
  445.      */
  446.     sorted.arc_childlist = 0;
  447.     for (  (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist);
  448.         arcp ;
  449.        (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) {
  450.         /*
  451.          *    consider *arcp as disconnected
  452.          *    insert it into sorted
  453.          */
  454.     for (   prevp = &sorted ;
  455.         prevp -> arc_childlist ;
  456.         prevp = prevp -> arc_childlist ) {
  457.         if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) {
  458.         break;
  459.         }
  460.     }
  461.     arcp -> arc_childlist = prevp -> arc_childlist;
  462.     prevp -> arc_childlist = arcp;
  463.     }
  464.     /*
  465.      *    reattach sorted children to parent
  466.      */
  467.     parentp -> children = sorted.arc_childlist;
  468. }
  469.  
  470. sortparents( childp )
  471.     nltype    *childp;
  472. {
  473.     arctype    *arcp;
  474.     arctype    *detachedp;
  475.     arctype    sorted;
  476.     arctype    *prevp;
  477.  
  478.     /*
  479.      *    unlink parents from child,
  480.      *    then insertion sort back on to sorted's parents.
  481.      *        *arcp    the arc you have detached and are inserting.
  482.      *        *detachedp    the rest of the arcs to be sorted.
  483.      *        sorted    arc list onto which you insertion sort.
  484.      *        *prevp    arc before the arc you are comparing.
  485.      */
  486.     sorted.arc_parentlist = 0;
  487.     for (  (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist);
  488.         arcp ;
  489.        (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) {
  490.         /*
  491.          *    consider *arcp as disconnected
  492.          *    insert it into sorted
  493.          */
  494.     for (   prevp = &sorted ;
  495.         prevp -> arc_parentlist ;
  496.         prevp = prevp -> arc_parentlist ) {
  497.         if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) {
  498.         break;
  499.         }
  500.     }
  501.     arcp -> arc_parentlist = prevp -> arc_parentlist;
  502.     prevp -> arc_parentlist = arcp;
  503.     }
  504.     /*
  505.      *    reattach sorted arcs to child
  506.      */
  507.     childp -> parents = sorted.arc_parentlist;
  508. }
  509.  
  510.     /*
  511.      *    print a cycle header
  512.      */
  513. printcycle( cyclep )
  514.     nltype    *cyclep;
  515. {
  516.     char    kirkbuffer[ BUFSIZ ];
  517.  
  518.     sprintf( kirkbuffer , "[%d]" , cyclep -> index );
  519.     printf( "%-6.6s %5.1f %7.2f %11.2f %7d" ,
  520.         kirkbuffer ,
  521.         100 * ( cyclep -> propself + cyclep -> propchild ) / printtime ,
  522.         cyclep -> propself / hz ,
  523.         cyclep -> propchild / hz ,
  524.         cyclep -> ncall );
  525.     if ( cyclep -> selfcalls != 0 ) {
  526.     printf( "+%-7d" , cyclep -> selfcalls );
  527.     } else {
  528.     printf( " %7.7s" , "" );
  529.     }
  530.     printf( " <cycle %d as a whole>\t[%d]\n" ,
  531.         cyclep -> cycleno , cyclep -> index );
  532. }
  533.  
  534.     /*
  535.      *    print the members of a cycle
  536.      */
  537. printmembers( cyclep )
  538.     nltype    *cyclep;
  539. {
  540.     nltype    *memberp;
  541.  
  542.     sortmembers( cyclep );
  543.     for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) {
  544.     printf( "%6.6s %5.5s %7.2f %11.2f %7d" , 
  545.         "" , "" , memberp -> propself / hz , memberp -> propchild / hz ,
  546.         memberp -> ncall );
  547.     if ( memberp -> selfcalls != 0 ) {
  548.         printf( "+%-7d" , memberp -> selfcalls );
  549.     } else {
  550.         printf( " %7.7s" , "" );
  551.     }
  552.     printf( "     " );
  553.     printname( memberp );
  554.     printf( "\n" );
  555.     }
  556. }
  557.  
  558.     /*
  559.      *    sort members of a cycle
  560.      */
  561. sortmembers( cyclep )
  562.     nltype    *cyclep;
  563. {
  564.     nltype    *todo;
  565.     nltype    *doing;
  566.     nltype    *prev;
  567.  
  568.     /*
  569.      *    detach cycle members from cyclehead,
  570.      *    and insertion sort them back on.
  571.      */
  572.     todo = cyclep -> cnext;
  573.     cyclep -> cnext = 0;
  574.     for (  (doing = todo)&&(todo = doing -> cnext);
  575.         doing ;
  576.        (doing = todo )&&(todo = doing -> cnext )){
  577.     for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) {
  578.         if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) {
  579.         break;
  580.         }
  581.     }
  582.     doing -> cnext = prev -> cnext;
  583.     prev -> cnext = doing;
  584.     }
  585. }
  586.  
  587.     /*
  588.      *    major sort is on propself + propchild,
  589.      *    next is sort on ncalls + selfcalls.
  590.      */
  591. int
  592. membercmp( this , that )
  593.     nltype    *this;
  594.     nltype    *that;
  595. {
  596.     double    thistime = this -> propself + this -> propchild;
  597.     double    thattime = that -> propself + that -> propchild;
  598.     long    thiscalls = this -> ncall + this -> selfcalls;
  599.     long    thatcalls = that -> ncall + that -> selfcalls;
  600.  
  601.     if ( thistime > thattime ) {
  602.     return GREATERTHAN;
  603.     }
  604.     if ( thistime < thattime ) {
  605.     return LESSTHAN;
  606.     }
  607.     if ( thiscalls > thatcalls ) {
  608.     return GREATERTHAN;
  609.     }
  610.     if ( thiscalls < thatcalls ) {
  611.     return LESSTHAN;
  612.     }
  613.     return EQUALTO;
  614. }
  615.     /*
  616.      *    compare two arcs to/from the same child/parent.
  617.      *    - if one arc is a self arc, it's least.
  618.      *    - if one arc is within a cycle, it's less than.
  619.      *    - if both arcs are within a cycle, compare arc counts.
  620.      *    - if neither arc is within a cycle, compare with
  621.      *        arc_time + arc_childtime as major key
  622.      *        arc count as minor key
  623.      */
  624. int
  625. arccmp( thisp , thatp )
  626.     arctype    *thisp;
  627.     arctype    *thatp;
  628. {
  629.     nltype    *thisparentp = thisp -> arc_parentp;
  630.     nltype    *thischildp = thisp -> arc_childp;
  631.     nltype    *thatparentp = thatp -> arc_parentp;
  632.     nltype    *thatchildp = thatp -> arc_childp;
  633.     double    thistime;
  634.     double    thattime;
  635.  
  636. #   ifdef DEBUG
  637.     if ( debug & TIMEDEBUG ) {
  638.         printf( "[arccmp] " );
  639.         printname( thisparentp );
  640.         printf( " calls " );
  641.         printname ( thischildp );
  642.         printf( " %f + %f %d/%d\n" ,
  643.             thisp -> arc_time , thisp -> arc_childtime ,
  644.             thisp -> arc_count , thischildp -> ncall );
  645.         printf( "[arccmp] " );
  646.         printname( thatparentp );
  647.         printf( " calls " );
  648.         printname( thatchildp );
  649.         printf( " %f + %f %d/%d\n" ,
  650.             thatp -> arc_time , thatp -> arc_childtime ,
  651.             thatp -> arc_count , thatchildp -> ncall );
  652.         printf( "\n" );
  653.     }
  654. #   endif DEBUG
  655.     if ( thisparentp == thischildp ) {
  656.         /* this is a self call */
  657.     return LESSTHAN;
  658.     }
  659.     if ( thatparentp == thatchildp ) {
  660.         /* that is a self call */
  661.     return GREATERTHAN;
  662.     }
  663.     if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 &&
  664.     thisparentp -> cycleno == thischildp -> cycleno ) {
  665.         /* this is a call within a cycle */
  666.     if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
  667.         thatparentp -> cycleno == thatchildp -> cycleno ) {
  668.         /* that is a call within the cycle, too */
  669.         if ( thisp -> arc_count < thatp -> arc_count ) {
  670.         return LESSTHAN;
  671.         }
  672.         if ( thisp -> arc_count > thatp -> arc_count ) {
  673.         return GREATERTHAN;
  674.         }
  675.         return EQUALTO;
  676.     } else {
  677.         /* that isn't a call within the cycle */
  678.         return LESSTHAN;
  679.     }
  680.     } else {
  681.         /* this isn't a call within a cycle */
  682.     if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
  683.         thatparentp -> cycleno == thatchildp -> cycleno ) {
  684.         /* that is a call within a cycle */
  685.         return GREATERTHAN;
  686.     } else {
  687.         /* neither is a call within a cycle */
  688.         thistime = thisp -> arc_time + thisp -> arc_childtime;
  689.         thattime = thatp -> arc_time + thatp -> arc_childtime;
  690.         if ( thistime < thattime )
  691.         return LESSTHAN;
  692.         if ( thistime > thattime )
  693.         return GREATERTHAN;
  694.         if ( thisp -> arc_count < thatp -> arc_count )
  695.         return LESSTHAN;
  696.         if ( thisp -> arc_count > thatp -> arc_count )
  697.         return GREATERTHAN;
  698.         return EQUALTO;
  699.     }
  700.     }
  701. }
  702.  
  703. int
  704. namecmp( npp1 , npp2 )
  705.     nltype **npp1, **npp2;
  706. {
  707.     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
  708. }
  709.  
  710. printindex()
  711. {
  712.     nltype        **namesortnlp;
  713.     register nltype    *nlp;
  714.     int            index, nnames, todo, i, j;
  715.     char        peterbuffer[20];
  716.  
  717.     /*
  718.      *    Now, sort regular function name alphbetically
  719.      *    to create an index.
  720.      */
  721.     namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
  722.     if ( namesortnlp == (nltype **) 0 ) {
  723.     fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
  724.     }
  725.     for ( index = 0 , nnames = 0 ; index < nname ; index++ ) {
  726.     if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 )
  727.         continue;
  728.     namesortnlp[nnames++] = &nl[index];
  729.     }
  730.     qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp );
  731.     for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) {
  732.     namesortnlp[todo++] = &cyclenl[index];
  733.     }
  734.     printf( "\f\nIndex by function name\n\n" );
  735.     index = ( todo + 2 ) / 3;
  736.     for ( i = 0; i < index ; i++ ) {
  737.     for ( j = i; j < todo ; j += index ) {
  738.         nlp = namesortnlp[ j ];
  739.         if ( nlp -> printflag ) {
  740.         sprintf( peterbuffer , "[%d]" , nlp -> index );
  741.         } else {
  742.         sprintf( peterbuffer , "(%d)" , nlp -> index );
  743.         }
  744.         if ( j < nnames ) {
  745.         printf( "%6.6s " , peterbuffer );
  746.         if (bsd_style_output)
  747.             printf ("%-19.19s" , nlp->name);
  748.         else {
  749.             int size = printnameonly(nlp);
  750.             for ( ; size < 19; size++) putchar(' ');
  751.         }
  752.         } else {
  753.         printf( "%6.6s " , peterbuffer );
  754.         sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno );
  755.         printf( "%-19.19s" , peterbuffer );
  756.         }
  757.     }
  758.     printf( "\n" );
  759.     }
  760.     free( namesortnlp );
  761. }
  762.  
  763. PTR
  764. xmalloc (size)
  765.      long size;
  766. {
  767.     PTR val = (PTR) malloc (size);
  768.     if (val == NULL) {
  769.     fprintf (stderr, "virtual memory exhaused\n");
  770.     exit (1);
  771.     }
  772.     return val;
  773. }
  774.  
  775. PTR
  776. xrealloc (oldval, size)
  777.      PTR oldval;
  778.      long size;
  779. {
  780.     PTR val = (PTR) realloc (oldval, size);
  781.     if (val == NULL) {
  782.     fprintf (stderr, "virtual memory exhaused\n");
  783.     exit (1);
  784.     }
  785.     return val;
  786. }
  787.  
  788.